"""FFmpeg包装器"""

import asyncio
import subprocess
from pathlib import Path
from typing import List, Optional, Dict, Any

from ..scheduler.task import TranscodeTask


class FFmpegWrapper:
    """FFmpeg包装器类"""
    
    def __init__(self):
        self.ffmpeg_path = self._find_ffmpeg()
    
    def _find_ffmpeg(self) -> str:
        """查找FFmpeg可执行文件"""
        # 优先检查系统PATH
        import shutil
        
        ffmpeg_path = shutil.which("ffmpeg")
        if ffmpeg_path:
            return ffmpeg_path
        
        # 检查常见安装路径
        common_paths = [
            "/usr/bin/ffmpeg",
            "/usr/local/bin/ffmpeg",
            "C:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe",
            "C:\\ffmpeg\\bin\\ffmpeg.exe",
        ]
        
        for path in common_paths:
            if Path(path).exists():
                return path
        
        raise RuntimeError("未找到FFmpeg可执行文件")
    
    async def encode_task(self, task: TranscodeTask) -> bool:
        """使用FFmpeg执行转码任务"""
        try:
            # 构建FFmpeg命令
            cmd = self._build_ffmpeg_command(task)
            
            # 启动进程
            process = await asyncio.create_subprocess_exec(
                *cmd,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            
            task.start()
            
            # 处理输出
            await self._monitor_process(process, task)
            
            # 等待进程完成
            return_code = await process.wait()
            
            if return_code == 0:
                task.complete()
                return True
            else:
                task.fail(f"FFmpeg进程返回错误代码: {return_code}")
                return False
                
        except Exception as e:
            task.fail(f"FFmpeg转码失败: {e}")
            return False
    
    def _build_ffmpeg_command(self, task: TranscodeTask) -> List[str]:
        """构建FFmpeg命令"""
        cmd = [self.ffmpeg_path, "-y"]  # -y 覆盖输出文件
        
        # 输入文件
        cmd.extend(["-i", str(task.input_path)])
        
        # 视频编码参数
        cmd.extend(["-c:v", self._get_video_codec(task)])
        cmd.extend(["-preset", task.quality_preset])
        cmd.extend(["-crf", "23"])
        
        # 音频编码参数
        cmd.extend(["-c:a", "aac"])
        cmd.extend(["-b:a", "128k"])
        
        # 输出文件
        cmd.append(str(task.output_path))
        
        return cmd
    
    def _get_video_codec(self, task: TranscodeTask) -> str:
        """获取视频编码器"""
        codec_map = {
            "nvidia": "h264_nvenc",
            "amd": "h264_amf",
            "intel": "h264_qsv",
            "auto": "libx264",
        }
        return codec_map.get(task.gpu_type, "libx264")
    
    async def _monitor_process(self, process: asyncio.subprocess.Process, task: TranscodeTask) -> None:
        """监控进程输出"""
        # 这里需要解析FFmpeg的输出来获取进度信息
        # 由于FFmpeg进度信息在stderr中，我们需要处理stderr流
        
        async def read_stderr():
            while True:
                line = await process.stderr.readline()
                if not line:
                    break
                
                line_str = line.decode('utf-8', errors='ignore').strip()
                
                # 解析进度信息
                progress = self._parse_progress(line_str)
                if progress is not None:
                    task.update_progress(progress)
                
                # 解析FPS信息
                fps = self._parse_fps(line_str)
                if fps is not None:
                    task.current_fps = fps
        
        # 启动读取任务
        await asyncio.create_task(read_stderr())
    
    def _parse_progress(self, line: str) -> Optional[float]:
        """解析进度信息"""
        # FFmpeg进度格式示例: frame=  123 fps= 25.0 time=00:00:04.92
        import re
        
        # 匹配时间信息
        time_match = re.search(r'time=(\d+):(\d+):(\d+)\.(\d+)', line)
        if time_match:
            hours = int(time_match.group(1))
            minutes = int(time_match.group(2))
            seconds = int(time_match.group(3))
            milliseconds = int(time_match.group(4))
            
            total_seconds = hours * 3600 + minutes * 60 + seconds + milliseconds / 100
            
            # 这里需要知道总时长才能计算进度百分比
            # 在实际应用中，需要先获取视频总时长
            return None
        
        return None
    
    def _parse_fps(self, line: str) -> Optional[float]:
        """解析FPS信息"""
        import re
        
        fps_match = re.search(r'fps=\s*(\d+(?:\.\d+)?)', line)
        if fps_match:
            return float(fps_match.group(1))
        
        return None
    
    async def get_video_info(self, file_path: Path) -> Dict[str, Any]:
        """获取视频信息"""
        try:
            cmd = [
                self.ffmpeg_path,
                "-i", str(file_path),
                "-hide_banner"
            ]
            
            process = await asyncio.create_subprocess_exec(
                *cmd,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            
            _, stderr = await process.communicate()
            
            # 解析FFmpeg输出
            return self._parse_ffmpeg_info(stderr.decode('utf-8', errors='ignore'))
            
        except Exception as e:
            print(f"获取视频信息失败: {e}")
            return {}
    
    def _parse_ffmpeg_info(self, output: str) -> Dict[str, Any]:
        """解析FFmpeg信息输出"""
        import re
        
        info = {}
        
        # 解析时长
        duration_match = re.search(r'Duration: (\d+):(\d+):(\d+)\.(\d+)', output)
        if duration_match:
            hours = int(duration_match.group(1))
            minutes = int(duration_match.group(2))
            seconds = int(duration_match.group(3))
            info["duration"] = hours * 3600 + minutes * 60 + seconds
        
        # 解析视频流信息
        video_match = re.search(r'Video: ([^,]+)', output)
        if video_match:
            info["video_codec"] = video_match.group(1)
        
        # 解析分辨率
        resolution_match = re.search(r'(\d+)x(\d+)', output)
        if resolution_match:
            info["width"] = int(resolution_match.group(1))
            info["height"] = int(resolution_match.group(2))
        
        # 解析帧率
        fps_match = re.search(r'(\d+(?:\.\d+)?) fps', output)
        if fps_match:
            info["fps"] = float(fps_match.group(1))
        
        return info